package com.aispeech.task.api.service.impl;

import com.aispeech.task.api.data.vo.TaskId;
import com.aispeech.task.api.data.vo.TaskProgress;
import com.aispeech.task.api.service.TaskService;
import com.aispeech.task.common.config.RedisConfig;
import com.aispeech.task.common.data.constant.Progress;
import com.aispeech.task.common.data.domain.Task;
import com.aispeech.task.common.data.enums.APICode;
import com.aispeech.task.common.data.vo.response.Result;
import com.aispeech.task.common.utils.TaskUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.connection.stream.StreamRecords;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.StreamOperations;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

import static com.aispeech.task.common.config.RedisConfig.HASH_TASK_KEY;

@Service
@Slf4j
public class TaskServiceImpl implements TaskService {
    @Autowired
    @Qualifier("hashTaskOperations")
    private HashOperations<String, String, Task> opHash;

    @Autowired
    private StreamOperations<String, String, String> opStream;

    private Task getTaskFromRedis(String taskId, String productId) {
        return opHash.get(HASH_TASK_KEY, TaskUtils.field(taskId, productId));
    }

    @Override
    public Result progress(String taskId, String productId) {
        Task task = getTaskFromRedis(taskId, productId);

        if (task != null) {
            return Result.ok(TaskProgress.of(task.getProgress()));
        } else {
            return Result.fail(APICode.NOT_FOUND);
        }
    }

    @Override
    public Result result(String taskId, String productId) {
        Task task = getTaskFromRedis(taskId, productId);

        if (task != null) {
            if (task.isFinished())
                return Result.ok(task);
            else
                return Result.fail(APICode.NOT_FINISHED);
        } else {
            return Result.fail(APICode.NOT_FOUND);
        }
    }

    @Override
    public Result create(Map request, String productId) {
        Task task = Task.of(productId, request);

        String taskField = TaskUtils.field(task.getId(), productId);
        opHash.put(HASH_TASK_KEY, taskField, task);

        opStream.add(StreamRecords.string(new HashMap() {
            {
                put("taskId", taskField);
            }
        }).withStreamKey(RedisConfig.STREAM_NAME));

        return Result.ok(TaskId.of(task.getId()));

    }
}
